/*
 * KjDevice.h
 *
 *  Created on: Dec 6, 2011
 *      Author: kylintse
 */

#ifndef KJDEVICE_H_
#define KJDEVICE_H_

#include "gtype.h"

class KjDevice
{
public:
	KjDevice();
	virtual ~KjDevice();

public:
	// Point number
	qint32 pointCount(PVType vt);

	// Point manipulation
	bool addPoint(PVType vt,qint32 id);
	bool removePoint(PVType vt,qint32 id);
	bool clearPoint(PVType vt);

	// Point value read and write
	bool readPointValue(PVType vt,qint32 id,quint32& value);
	bool writePointValue(PVType vt,qint32 id,quint32 value);

	// Command exclusive
	bool lockForCommand(int timeout);
	void unLockForCommand();

private:
	QMap<qint32,quint32> m_ai;
	QMap<qint32,quint32> m_di;
	QMap<qint32,quint32> m_pi;

	QSemaphore* m_semCommand;
};

enum KjEventType
{
	ketAction=1,
	ketAlarm=2,
	ketSoe=3,
};

typedef struct _tKjEvent
{
	quint32 devId;
	KjEventType type;
	qint32 code;
	quint32 timeOccur;
	QByteArray value;
}KjEvent;

typedef struct _tKjEventProcessor
{
	QMutex lock;
	QSemaphore* sem;
	QList<quint32> lstDev;
	QQueue<KjEvent*> events;
}KjEventProcessor;

typedef struct _tKjCommand
{
	QString source;
	quint32 devId;
	qint8 needNotify;
	quint8 notifyFinish;
	quint32 serverType;
	QByteArray data;
	QByteArray dataNotify;
	QDateTime startTime;
}KjCommand;

typedef struct _tKjCommandProcessor
{
	quint32 ethIdCare;
	QSemaphore* sem;
	QList<quint32> lstDev;
	QMutex lockCmd;
	QQueue<KjCommand*> commands;
}KjCommandProcessor;

typedef struct _tKjCommandNotifyProcessor
{
	QSemaphore* sem;
	QMutex lockNotify;
	QQueue<KjCommand*> notifies;
}KjCommandNotifyProcessor;


#define DG_LIMIT		2048

class KjDeviceList
{
public:
	KjDeviceList();
	virtual ~KjDeviceList();

public:
	bool init();

	bool putDatagram(const QByteArray& data);
	bool getDatagram(QByteArray& data,int timeout);

	qint32 pointCount(quint32 devId,PVType vt);

	bool readPointValue(quint32 devId,PVType vt,qint32 id,quint32& value);
	bool writePointValue(quint32 devId,PVType vt,qint32 id,quint32 value);

	bool registerEventProcessor(const QString& processorId,const QList<quint32>& lstDev);
	bool unregisterEventProcessor(const QString& processorId);

	bool putEvent(quint32 devId,KjEventType type,qint32 code,quint32 timeOccur,
			const QByteArray& value);
	bool getEvent(const QString& processorId,quint32& devId,KjEventType& type,qint32& code,
			quint32& timeOccur,QByteArray& value,int timeout);

	bool registerCommandProcessor(quint32 processorId,const QList<quint32>& lstDev,quint32 ethIdCare=2);
	bool unRegisterCommandProcessor(quint32 processorId);

	bool regiserCommandNotifyProcessor(const QString& source);
	bool unRegisterCommandNotifyProcessor(const QString& source);

	bool putCommand(const QString& source,quint32 ethId,quint32 serverType,
			quint32 devId,const QByteArray& data,qint8 needNotify,
			int timeout);
	bool getCommand(quint32 processorId,QString& source,quint32& serverType,
			quint32& devId,QByteArray& data,int timeout);

	bool putCommandNotify(const QString& source,quint32 devId,const QByteArray& data,
			quint8 notifyFinish);
	bool getCommandNotify(const QString& source,quint32& devId,QByteArray& data,
			int timeout,quint8& notifyFinish);

private:
	QMap<quint32,KjDevice*> m_devices;

	QMutex m_lockDatagram;
	QSemaphore* m_semDatagram;
	QQueue<QByteArray> m_datagrams;

	QReadWriteLock m_lockEventProcessor;
	QMap<QString,KjEventProcessor*> m_eventProcessors;

	QReadWriteLock m_lockCmdProcessor;
	QMap<quint32,KjCommandProcessor*> m_cmdProcessors;

	QReadWriteLock m_lockCmdNotifyProcessor;
	QMap<QString,KjCommandNotifyProcessor*> m_cmdNotifyProcessors;

	QReadWriteLock m_lockCommandExcuting;
	QList<KjCommand*> m_lstCommandExcuting;

};

#endif /* KJDEVICE_H_ */
